#include "AttributeModel.h"
#include "Editor.h"
#include <QShortcut>

AttributeModel::AttributeModel() : currentNode(0) {
	insertRows(0, 1);
	setData(createIndex(0, 0, 0), QVariant(100));
	setData(createIndex(0, 1, 0), QVariant(200));

	QShortcut* deleteS = new QShortcut(QKeySequence(Qt::Key_Delete), Editor::ins().getUI().attributeList);
	deleteS->setContext(Qt::WidgetShortcut);
	connect(deleteS,
		SIGNAL(activated()), this, SLOT(removeAttribute()));
}

AttributeModel::~AttributeModel() {
}

QVariant AttributeModel::data(const QModelIndex &index, int role) const {
	if (currentNode == 0) return QVariant();
	if (!index.isValid()) return QVariant();
	if (role != Qt::DisplayRole) return QVariant();
	
	int id = index.internalId();
	if (id >= key.size())
		return QVariant();
	if (index.column() == 0)
		return key[id];
	else
		return currentNode->attr[key[id]];
}
Qt::ItemFlags AttributeModel::flags(const QModelIndex &index) const {
	if (currentNode == 0) return 0;
	return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable;
}
QVariant AttributeModel::headerData(int section, Qt::Orientation orientation, int role) const {
	if (orientation == Qt::Vertical) return QVariant();
	if (role == Qt::DisplayRole) {
		if (section == 0)
			return "Field";
		if (section == 1)
			return "Value";
	}
	return QVariant();

}
QModelIndex AttributeModel::index(int row, int column, const QModelIndex &parent) const {
	return createIndex(row, column, row);
}
QModelIndex AttributeModel::parent(const QModelIndex &index) const {
	return QModelIndex();
}
int AttributeModel::rowCount(const QModelIndex &parent) const {
	return key.size() + 1;
}
int AttributeModel::columnCount(const QModelIndex &parent) const {
	return 2;
}

void AttributeModel::selectNode(Node* node) {
	if (currentNode == node) return;
	currentNode = node;
	int ks = key.size();
	if (ks > 0) {
		beginRemoveRows(QModelIndex(), 0, ks - 1);
		key.clear();
		endRemoveRows();
	}
	if (currentNode != 0) {
		int as = currentNode->attr.size();
		if (as > 0) {
			beginInsertRows(QModelIndex(), 0, as - 1);
			for(QHash<QString, QVariant>::iterator it = currentNode->attr.begin(); it != currentNode->attr.end(); ++it) {
				key.append(it.key());
			}
			endInsertRows();
		}
	}
}

void AttributeModel::removeNodeAttr(Node* node, const QString& key) {
	if (node != currentNode) {
		node->attr.remove(key);
		Editor::ins().selectNode(node);
	}else {
		int i = this->key.indexOf(key);
		beginRemoveRows(QModelIndex(), i, i);
		this->key.remove(i);
		endRemoveRows();
		node->attr.remove(key);
	}
}

void AttributeModel::setNodeAttr(Node* node, const QString &key, const QVariant &val) {
	if (currentNode != node) Editor::ins().selectNode(node);
	int id = this->key.indexOf(key);
	node->attr[key] = val;
	if (id != -1) {
		QModelIndex idx = createIndex(id, 1, id);
		emit dataChanged(idx, idx);
	} else {
		int ks = this->key.size();
		beginInsertRows(QModelIndex(), ks, ks);
		this->key.append(key);
		endInsertRows();
	}
}

void AttributeModel::moveNodeAttr(Node* node, const QString& key, const QString& newKey) {
	if (currentNode != node) Editor::ins().selectNode(node);

	int id = this->key.indexOf(key);
	if (id != -1) {
		this->key[id] = newKey;
		node->attr[newKey] = node->attr[key];
		node->attr.remove(key);
		QModelIndex idx = createIndex(id, 0, id);
		emit dataChanged(idx, idx);
	}
}


void AttributeModel::removeNodeAttrByIndex(Node *node, int idx) {
	beginRemoveRows(QModelIndex(), idx, idx);
	node->attr.remove(key[idx]);
	key.remove(idx);
	endRemoveRows();
}

void AttributeModel::restoreNodeAttrByIndex(Node* node, int idx, const QString &key, const QVariant& val) {
	beginInsertRows(QModelIndex(), idx, idx);
	this->key.insert(idx, key);
	node->attr[key] = val;
	endInsertRows();
}

bool AttributeModel::setData(const QModelIndex & index, const QVariant & value, int role) {
	if (role == Qt::EditRole) {
		if (currentNode == 0) return false;

		int id = index.internalId();
		int col = index.column();
		if (id == key.size()) {
			if (col != 0) return false;

			QString s = qvariant_cast<QString>(value); 
			if (s == "") return false;
			if (currentNode->attr.find(s) == currentNode->attr.end()) {	
				beginInsertRows(QModelIndex(), key.size(), key.size());
				key.append(s);
				currentNode->attr[s] = QVariant(tr(""));
				endInsertRows();
				Editor::ins().pushCommand(new AttributeCommand(this, currentNode, s, QVariant(tr("")), QVariant()));
				return true;
			} else return false;
		} else {
			QString& k = key[id];
			if (col == 0) {
				//key
				QString s = qvariant_cast<QString>(value);
				if (k == s) return false;
				if (currentNode->attr.find(s) == currentNode->attr.end()) {
					Editor::ins().pushCommand(new MoveAttributeCommand(this, currentNode, s, k));
					currentNode->attr[s] = currentNode->attr[k];
					currentNode->attr.remove(k);
					k = s;
					return true;
				}
				return false;
			} else {
				//value
				Editor::ins().pushCommand(new AttributeCommand(this, currentNode, k, value, currentNode->attr[k]));
				currentNode->attr[k] = value;
			}
		}
	}	
	return true;
}

void AttributeModel::removeAttribute() {
	if (currentNode == 0) return;
	QModelIndex idx = Editor::ins().getUI().attributeList->currentIndex();
	int r = idx.row();
	if (r == key.size()) return;
	Editor::ins().invokeNewCommand(new RemoveAttributeCommand(this, currentNode, r, key[r], currentNode->attr[key[r]]));
}

